package com.google.code.p.localspinner;

import java.util.LinkedList;
import java.util.List;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;

import com.google.code.p.localspinner.database.UserdataAdapter;
import com.google.code.p.localspinner.iva.MoviesSearch;
import com.google.code.p.localspinner.model.Item;
import com.google.code.p.localspinner.model.ItemList;
import com.google.code.p.localspinner.model.ItemList.Type;
import com.google.code.p.localspinner.yahoo.LocalSearcher;
import com.google.code.p.localspinner.yahoo.UpcommingSearcher;

/**
 * A helper class that handles some UI work of searching such as showing a loading dialog and executing
 * search in a background thread
 * 
 * @author liangj01
 *
 */
class SearchHelper {
    private static final String NO_RESULTS_FOUND_PLEASE_ADJUST_YOUR_QUERY_AND_TRY_AGAIN = 
        "No results found, please adjust your query and try again. \nHint: try expanding your input location to a larger area.";
    private static final String NO_RESULTS_FOUND = 
        "No results found, please try again later.";
    private static final String SEARCH_FAILED_PLEASE_TRY_AGAIN = "Search failed, please try again";
    private static final String ERROR = "ERROR";
    public static final String ITEMS = "items";
//    private final ProgressDialog loadingDialog;
    private LocalSearcher localSearcher;
    private UpcommingSearcher upcomingSearcher;
    private MoviesSearch movieSearcher;
    private final Activity activity;
    private volatile boolean searching = false;
    private final Handler handler;
    public static enum SearchType{
      LOCAL, UPCOMING
    }
    
    public SearchHelper(final Activity activity){
        this.activity = activity;
        this.handler = new Handler(){
            @Override
            public void handleMessage(Message m) {
                Toast text = Toast.makeText(activity, 
                        m.getData().getString(ERROR), Toast.LENGTH_SHORT);
                text.show();
            }
        };

        try {
          localSearcher =  new LocalSearcher();
          upcomingSearcher = new UpcommingSearcher();
          movieSearcher = new MoviesSearch();
        } catch (SearchException e3) {
          Log.e(LocalSpinner.class.getName(), "no searcher");
        }
        
    }
    
    public void gotoTrailerUrl(final String query){
        if(searching){
            Log.d(SearchHelper.class.toString(), "searching in progress, return...");
              return;
          }
          
            activity.showDialog(LocalSpinner.ID_DIALOG_SEARCHING);
          new Thread(new Runnable(){

              @Override
              public void run() {
                  String url = null;
                  try {
                      searching = true;
                      url = movieSearcher.getYoutubeTrailer(query);
                  } catch (Exception e) {
                      Log.e(SearchHelper.class.getName(), "Search failed", e);
                      sendError("Unable to find top movies: "+ e.getMessage());
                      return;
                  }finally{
                      searching = false;
                      activity.dismissDialog(Search.ID_DIALOG_SEARCHING);
                  }
                  if(url == null){
                      url = "http://www.youtube.com";
                  }
                  activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
                  activity.finish();
              }
              
          }).start();
    }
    
    public void searchTopMovies(){
      if(searching){
        Log.d(SearchHelper.class.toString(), "searching in progress, return...");
          return;
      }
      
      activity.showDialog(Search.ID_DIALOG_SEARCHING);
      
      new Thread(new Runnable(){

          @Override
          public void run() {
              ItemList searchResult = null; 
              try {
                  searching = true;
                  searchResult = movieSearcher.searchTopMovies();
                  searchResult.setType(Type.MOVIE);
                  fillList(searchResult, StaticMemory.ITEMS_EXTRAS);
              } catch (Exception e) {
                  Log.e(SearchHelper.class.getName(), "Search failed", e);
                  sendError("Unable to find top movies: "+ e.getMessage());
                  return;
              }finally{
                  searching = false;
                  activity.dismissDialog(Search.ID_DIALOG_SEARCHING);
              }
              
              if(searchResult == null || searchResult.size() < 1){
                  sendError(NO_RESULTS_FOUND);                    
                  return;
              }
              Intent i = new Intent(activity, LocalSpinner.class);                
              i.putExtra(ITEMS, searchResult);
              activity.startActivityForResult(i, -1);
          }
          
      }).start();
    }
    
    public void searchFromDb(final UserdataAdapter adapter, final long listId){
      if(searching){
        Log.d(SearchHelper.class.toString(), "searching in progress, return...");
          return;
      }
      
      activity.showDialog(Search.ID_DIALOG_SEARCHING);
      
      new Thread(new Runnable(){

          @Override
          public void run() {
              ItemList searchResult = null; 
              try {
                  searching = true;
                  searchResult = adapter.getItemList(listId);
                  searchResult.setType(Type.USER);
                  fillList(searchResult, StaticMemory.ITEMS_EXTRAS);
              } catch (Exception e) {
                  Log.e(SearchHelper.class.getName(), "Search failed", e);
                  sendError("Unable to retrieve list from database: "+ e.getMessage());
                  return;
              }finally{
                  searching = false;
                  activity.dismissDialog(Search.ID_DIALOG_SEARCHING);
              }

              Intent i = new Intent(activity, LocalSpinner.class);                
              i.putExtra(ITEMS, searchResult);
              activity.startActivityForResult(i, -1);
          }
          
      }).start();
    }
    
    
    /**
     * Execute a listing search in a background thread, cancels the loading dialog and start the search result activity when finishes
     * 
     * @param activity
     * @param listingSearcher
     * @param criteria
     * @param loadingDialog
     */
    public void startSearch(final String query, final String location, final SearchType type){
    
        if(searching){
          Log.d(SearchHelper.class.toString(), "searching in progress, return...");
            return;
        }
        
        activity.showDialog(Search.ID_DIALOG_SEARCHING);
        
        new Thread(new Runnable(){

            @Override
            public void run() {
                ItemList searchResult = null; 
                try {
                    searching = true;
                    if(type == SearchType.UPCOMING){
                      searchResult = upcomingSearcher.searchPopularEvents(location);
                      searchResult.setType(Type.EVENTS);
                      fillList(searchResult, StaticMemory.ITEMS_EXTRAS);
                    }else{
                      searchResult = localSearcher.search(query, location);
                      searchResult.setType(Type.LOCAL);
                      fillList(searchResult, StaticMemory.ITEMS_EXTRAS);
                    }
                } catch (Exception e) {
                    Log.e(SearchHelper.class.getName(), "Search failed", e);
                    sendError(SEARCH_FAILED_PLEASE_TRY_AGAIN);
                    return;
                }finally{
                    searching = false;
                    activity.dismissDialog(Search.ID_DIALOG_SEARCHING);
                }
                
                if(searchResult == null || searchResult.size() < 1){
                    sendError(NO_RESULTS_FOUND_PLEASE_ADJUST_YOUR_QUERY_AND_TRY_AGAIN);                    
                    return;
                }
                
                Intent i = new Intent(activity, LocalSpinner.class);                
                i.putExtra(ITEMS, searchResult);
                activity.startActivityForResult(i, -1);
            }
            
        }).start();
    }
    
    public static void fillList(ItemList list, Item[] extras){
        if(list.size() <= 1 || (12%list.size()) == 0){
            return;
        }
        
        int factor = (int)12/list.size();
        if(factor > 1){
            List<Item> newList = new LinkedList<Item>();
            for(int f = 0; f < factor; f++){
                newList.addAll(list.getItems());
            }
            list.getItems().clear();
            list.getItems().addAll(newList);
        }
        int toAdd =  12 - list.size();
        for(int t =0; t< toAdd; t++){
            list.getItems().add(extras[t]);
        }
    }
    
    
    private void sendError(CharSequence errorMessage){
        Message msg = handler.obtainMessage();
        Bundle b = new Bundle();
        b.putCharSequence(ERROR, errorMessage);
        msg.setData(b);
        handler.sendMessage(msg);
    }
}
